"""
系统模型定义
包含系统日志等系统相关模型
"""
from datetime import datetime
from flask_sqlalchemy import SQLAlchemy
from ..timezone_utils import now as timezone_now

# 获取db实例
from . import db

class SystemLog(db.Model):
    """系统日志模型"""
    __tablename__ = 'system_logs'
    
    id = db.Column(db.Integer, primary_key=True)
    level = db.Column(db.String(20), nullable=False, index=True)  # TRACE, DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL, ALERT, EMERGENCY
    module = db.Column(db.String(100), nullable=False, index=True)  # 模块名称
    message = db.Column(db.Text, nullable=False)
    details = db.Column(db.Text)  # 详细信息，JSON格式
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), index=True)
    ip_address = db.Column(db.String(45))  # IP地址（IPv6需要45个字符）
    user_agent = db.Column(db.Text)  # 用户代理
    created_at = db.Column(db.DateTime, default=timezone_now, nullable=False, index=True)
    
    # 新增字段
    action = db.Column(db.String(100), index=True)  # 具体操作类型（create, update, delete, execute等）
    resource_type = db.Column(db.String(50), index=True)  # 资源类型（task, user, system, file等）
    resource_id = db.Column(db.String(100), index=True)  # 资源ID
    session_id = db.Column(db.String(100), index=True)  # 会话ID
    execution_time = db.Column(db.Float)  # 执行时间（毫秒）
    status_code = db.Column(db.Integer)  # HTTP状态码或操作结果码
    request_id = db.Column(db.String(100), index=True)  # 请求追踪ID
    parent_log_id = db.Column(db.Integer, db.ForeignKey('system_logs.id'))  # 父日志ID（用于关联）
    tags = db.Column(db.Text)  # 标签（JSON数组）
    severity = db.Column(db.Integer, default=0)  # 严重程度（0-10）
    request_method = db.Column(db.String(10))  # HTTP请求方法
    request_url = db.Column(db.Text)  # 请求URL
    response_size = db.Column(db.Integer)  # 响应大小（字节）
    error_code = db.Column(db.String(50))  # 错误代码
    stack_trace = db.Column(db.Text)  # 错误堆栈信息
    
    user = db.relationship('User', backref='logs')
    
    def to_dict(self):
        """转换为字典"""
        # 根据action和resource_type生成log_type
        log_type = self._generate_log_type()
        
        return {
            'id': self.id,
            'level': self.level,
            'module': self.module,
            'message': self.message,
            'details': self.details,
            'user_id': self.user_id,
            'ip_address': self.ip_address,
            'user_agent': self.user_agent,
            'created_at': self.created_at.isoformat() if self.created_at else None,
            'action': self.action,
            'resource_type': self.resource_type,
            'resource_id': self.resource_id,
            'session_id': self.session_id,
            'execution_time': self.execution_time,
            'status_code': self.status_code,
            'request_id': self.request_id,
            'parent_log_id': self.parent_log_id,
            'tags': self.tags,
            'severity': self.severity,
            'request_method': self.request_method,
            'request_url': self.request_url,
            'response_size': self.response_size,
            'error_code': self.error_code,
            'stack_trace': self.stack_trace,
            'log_type': log_type
        }
    
    def _generate_log_type(self):
        """根据action和resource_type生成log_type"""
        if not self.action:
            return None
            
        # 根据action和resource_type的组合生成对应的log_type
        action_mapping = {
            'login': 'LOGIN_ATTEMPT',
            'logout': 'LOGIN_ATTEMPT', 
            'login_success': 'LOGIN_ATTEMPT',
            'login_failed': 'LOGIN_ATTEMPT',
            'api_request': 'API_CALL',
            'create': 'USER_ACTION',
            'update': 'USER_ACTION',
            'delete': 'USER_ACTION',
            'execute': 'TASK_OPERATION',
            'start': 'TASK_OPERATION',
            'stop': 'TASK_OPERATION',
            'pause': 'TASK_OPERATION',
            'resume': 'TASK_OPERATION',
            'upload': 'FILE_OPERATION',
            'download': 'FILE_OPERATION',
            'file_create': 'FILE_OPERATION',
            'file_delete': 'FILE_OPERATION',
            'system_start': 'SYSTEM_EVENT',
            'system_stop': 'SYSTEM_EVENT',
            'backup': 'SYSTEM_EVENT',
            'restore': 'SYSTEM_EVENT',
            'permission_check': 'SECURITY_EVENT',
            'access_denied': 'SECURITY_EVENT',
            'unauthorized_access': 'SECURITY_EVENT',

        }
        
        # 首先尝试直接匹配action
        if self.action in action_mapping:
            return action_mapping[self.action]
            
        # 如果没有直接匹配，根据resource_type推断
        if self.resource_type:
            if self.resource_type == 'task':
                return 'TASK_OPERATION'
            elif self.resource_type == 'user':
                return 'USER_ACTION'
            elif self.resource_type == 'file':
                return 'FILE_OPERATION'
            elif self.resource_type == 'system':
                return 'SYSTEM_EVENT'
            elif self.resource_type == 'api':
                return 'API_CALL'
                
        # 默认返回USER_ACTION
        return 'USER_ACTION'
    
    def __repr__(self):
        return f'<SystemLog {self.level}: {self.message[:50]}>'

    @staticmethod
    def create_log(level, module, message, details=None, user_id=None, request=None, 
                   action=None, resource_type=None, resource_id=None, session_id=None,
                   execution_time=None, status_code=None, request_id=None, parent_log_id=None,
                   tags=None, severity=0, error_code=None, stack_trace=None, response_size=None):
        """创建日志记录的工具函数"""
        log = SystemLog(
            level=level,
            module=module,
            message=message,
            details=details,
            user_id=user_id,
            action=action,
            resource_type=resource_type,
            resource_id=resource_id,
            session_id=session_id,
            execution_time=execution_time,
            status_code=status_code,
            request_id=request_id,
            parent_log_id=parent_log_id,
            tags=tags,
            severity=severity,
            error_code=error_code,
            stack_trace=stack_trace,
            response_size=response_size
        )
        
        # 如果提供了request对象，提取相关信息
        if request:
            log.ip_address = request.remote_addr
            log.user_agent = request.headers.get('User-Agent')
            log.request_method = request.method
            log.request_url = request.url
            
            # 如果没有提供session_id，尝试从request中获取
            if not session_id and hasattr(request, 'session'):
                log.session_id = request.session.get('_id')
        
        return log


class SystemConfig(db.Model):
    """系统配置模型"""
    __tablename__ = 'system_configs'
    
    id = db.Column(db.Integer, primary_key=True)
    config_key = db.Column(db.String(100), unique=True, nullable=False, index=True)  # 配置键
    config_value = db.Column(db.Text, nullable=False)  # 配置值
    config_type = db.Column(db.String(20), nullable=False, default='string')  # 配置类型：string, int, float, bool, json
    description = db.Column(db.Text)  # 配置描述
    is_system = db.Column(db.Boolean, default=True, nullable=False)  # 是否为系统配置
    created_at = db.Column(db.DateTime, default=timezone_now, nullable=False)
    updated_at = db.Column(db.DateTime, default=timezone_now, onupdate=timezone_now, nullable=False)
    updated_by = db.Column(db.Integer, db.ForeignKey('users.id'))  # 更新者
    
    # 关系
    updater = db.relationship('User', backref='config_updates')
    
    def to_dict(self):
        """转换为字典"""
        return {
            'id': self.id,
            'config_key': self.config_key,
            'config_value': self.get_typed_value(),
            'config_type': self.config_type,
            'description': self.description,
            'is_system': self.is_system,
            'created_at': self.created_at.isoformat() if self.created_at else None,
            'updated_at': self.updated_at.isoformat() if self.updated_at else None,
            'updated_by': self.updated_by
        }
    
    def get_typed_value(self):
        """根据类型返回正确的值"""
        if self.config_type == 'int':
            return int(self.config_value)
        elif self.config_type == 'float':
            return float(self.config_value)
        elif self.config_type == 'bool':
            return self.config_value.lower() in ('true', '1', 'yes', 'on')
        elif self.config_type == 'json':
            import json
            return json.loads(self.config_value)
        else:
            return self.config_value
    
    def set_typed_value(self, value):
        """根据类型设置值"""
        if self.config_type == 'json':
            import json
            self.config_value = json.dumps(value)
        else:
            self.config_value = str(value)
    
    @staticmethod
    def get_config(key, default=None):
        """获取配置值"""
        config = SystemConfig.query.filter_by(config_key=key).first()
        if config:
            return config.get_typed_value()
        return default
    
    @staticmethod
    def set_config(key, value, config_type='string', description=None, user_id=None):
        """设置配置值"""
        config = SystemConfig.query.filter_by(config_key=key).first()
        if config:
            config.set_typed_value(value)
            config.updated_by = user_id
            config.updated_at = timezone_now()
        else:
            config = SystemConfig(
                config_key=key,
                config_type=config_type,
                description=description,
                updated_by=user_id
            )
            config.set_typed_value(value)
            db.session.add(config)
        
        db.session.commit()
        return config
    
    def __repr__(self):
        return f'<SystemConfig {self.config_key}={self.config_value}>'